package com.zy;

import org.activiti.engine.*;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.io.IOUtils;
import org.junit.Test;

import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.zip.ZipInputStream;

/**
 * @author: 13417
 * @since: 2024/4/13 15:06:05
 * @description:
 */
public class ActivitiDemo {

    /*
     *   测试流程部署
     */
    @Test
    public void testDeployment() {
        // 1.创建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        // 2.得到 RepositoryService 实例
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 3. 使用 repositoryService进行流程部署
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/evection.bpmn")  // 添加 bpmn资源
                .addClasspathResource("bpmn/evection.png")   // 添加 png资源
                .name("出差申请流程")
                .deploy();

        // 4. 输出部署信息
        System.out.println("流程部署ID==>" + deployment.getId());
        System.out.println("流程部署名称==>" + deployment.getName());
    }

    /*
     *  启动流程实例
     * */
    @Test
    public void testStartProcess() {
        // 1.创建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        // 2.获取 runtimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 3.根据流程定义的ID启动流程
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey("myEvection");

        // 4.输出内容
        System.out.println("流程定义的Id===>" + processInstance.getProcessDefinitionId());
        System.out.println("流程实例Id===>" + processInstance.getId());
        System.out.println("当前活动的Id===>" + processInstance.getActivityId());
    }

    /*
     *  查询个人待执行的任务
     * */
    @Test
    public void testFindPersonalTaskList() {
        // 1.创建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        // 2.获取 TaskService
        TaskService taskService = processEngine.getTaskService();

        // 3.根据流程key 和流程的负责人 查询任务
        List<Task> list = taskService.createTaskQuery()
                .processDefinitionKey("myEvection")
                .taskAssignee("zhangsan")
                .list();

        list.forEach(task -> {
            System.out.println("流程实例Id==>" + task.getProcessInstanceId());
            System.out.println("任务Id==>" + task.getId());
            System.out.println("任务负责人==>" + task.getAssignee());
            System.out.println("任务名称==>" + task.getName());
        });
    }

    /*
     *   完成个人任务
     * */
    @Test
    public void testCompleteTask() {
        // 1.创建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        // 2.获取 TaskService
        TaskService taskService = processEngine.getTaskService();

        // 3.根据流程key 和 任务的负责人 查询任务
        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvection")
                .taskAssignee("rose")
                .singleResult();

        System.out.println("流程实例Id==>" + task.getProcessInstanceId());
        System.out.println("任务Id==>" + task.getId());
        System.out.println("任务负责人==>" + task.getAssignee());
        System.out.println("任务名称==>" + task.getName());

        // 4. 根据任务的Id完成任务
        taskService.complete(task.getId());
    }

    /*
     *   使用 zip包进行批量的部署
     * */
    @Test
    public void deployProcessByZip() {
        // 1.获取 流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2.获取 RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 3.流程部署
        // 获取 资源包文件，构造成 zipInputStream
        InputStream inputStream = this.getClass()
                .getClassLoader()
                .getResourceAsStream("bpmn/evection.zip");
        ZipInputStream zipInputStream = new ZipInputStream(inputStream);

        //  4.使用压缩包的流进行流程部署
        Deployment deploy = repositoryService.createDeployment()
                .addZipInputStream(zipInputStream)
                .deploy();

        System.out.println("流程部署的Id" + deploy.getId());
        System.out.println("流程部署的名字" + deploy.getName());
    }

    /*
     *   查询流程定义信息
     * */
    @Test
    public void queryProcessDefinition() {
        // 1. 获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        // 2. 获取 repositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 3. 获取processDefinitionQuery对象
        ProcessDefinitionQuery processDefinitionQuery = repositoryService.createProcessDefinitionQuery();

        List<ProcessDefinition> processDefinitionList = processDefinitionQuery.processDefinitionKey("myEvection")
                .orderByProcessDefinitionVersion()
                .desc()
                .list();

        processDefinitionList.forEach(processDefinition -> {
            System.out.println("流程定义的Id==>" + processDefinition.getId());
            System.out.println("流程定义的Name==>" + processDefinition.getName());
            System.out.println("流程定义的版本==>" + processDefinition.getVersion());
            System.out.println("流程定义的Key==>" + processDefinition.getKey());
            System.out.println("流程部署的Key==>" + processDefinition.getDeploymentId());
        });
    }

    /*
     *   流程删除
     * */
    @Test
    public void deleteDeployment() {
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 流程部署的ID
        String deploymentId = "2501";
        repositoryService.deleteDeployment(deploymentId);
    }

    /*
     *   流程资源下载
     *   方案一：  使用Activiti 提供的Api,来下载资源文件，保存到文件目录
     *   方案二：  自己写代码从数据中下载文件，使用jdbc 对blob类型,clob类型数据读取出来,保存到目标文件
     *   解决 IO操作：commons-io.jar
     *   这里我们使用第一种方案 Activiti 提供的Api：RepositoryService
     * */
    @Test
    public void getDeployment() throws IOException {
        // 1. 得到引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        // 2.获取 RepositoryService
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 3. 根据流程key 获取流程定义对象
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionKey("myEvection")
                .singleResult();

        // 4.通过流程定义的信息 获取流程设计Id
        String deploymentId = processDefinition.getDeploymentId();

        System.out.println("流程定义ID====》" + deploymentId);

        // 获取png的流
        String pngName = processDefinition.getDiagramResourceName();
        // 5、通过repositoryService的方法，实现读取图片信息和bpmn 信息 png图片的流
        InputStream pngInput = repositoryService.getResourceAsStream(deploymentId, pngName);

        // 获取Bpmn的流
        String bpmnName = processDefinition.getResourceName();
        InputStream bpmnInput = repositoryService.getResourceAsStream(deploymentId, bpmnName);

        File pngFile = new File("G:\\study\\activiti\\activiti01\\src\\main\\resources\\bpmn\\11.png");
        File bpmnFile = new File("G:\\study\\activiti\\activiti01\\src\\main\\resources\\bpmn\\11.bpmn");

        FileOutputStream pngOutPut = new FileOutputStream(pngFile);
        FileOutputStream bpmnOutPut = new FileOutputStream(bpmnFile);
        //  7、输入流，输出流的转换
        IOUtils.copy(pngInput, pngOutPut);
        IOUtils.copy(bpmnInput, bpmnOutPut);

        // 8、关闭流
        bpmnOutPut.close();
        pngOutPut.close();
        bpmnInput.close();
        pngInput.close();
    }


    /*
     *   测试流程部署_uel表达式相关设计流程
     */
    @Test
    public void testDeployment_uel() {
        // 1.创建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

        // 2.得到 RepositoryService 实例
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 3. 使用 repositoryService进行流程部署
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/evection_uel.bpmn")  // 添加 bpmn资源
                .addClasspathResource("bpmn/evection_uel.png")   // 添加 png资源
                .name("出差申请流程")
                .deploy();

        // 4. 输出部署信息
        System.out.println("流程部署ID==>" + deployment.getId());
        System.out.println("流程部署名称==>" + deployment.getName());
    }


    /*
     *  启动uel表达式相关流程实例
     * */
    @Test
    public void testStartProcess_Uel() {
        // 1.创建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2.获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 3.设置assignee的取值，用户可以在界面上设置流程的执行
        HashMap<String, Object> assigneeMap = new HashMap<>();
        assigneeMap.put("Assignee0", "张三");
        assigneeMap.put("Assignee1", "李经理");
        assigneeMap.put("Assignee2", "王总");
        assigneeMap.put("Assignee3", "赵财务");
        // 启动流程实例，同时还要设置流程定义的assignee的值
        runtimeService.startProcessInstanceByKey("myEvection_uel", assigneeMap);

        System.out.println(processEngine.getName());
    }

    /*
     *   完成个人任务
     * */
    @Test
    public void testCompleteTask_Uel() {
        // 1.获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取 TaskService
        TaskService taskService = processEngine.getTaskService();

        Task task = taskService.createTaskQuery()
                .processDefinitionKey("myEvection_uel")
                .taskAssignee("123")
                .singleResult();

        System.out.println("流程实例Id==>" + task.getProcessInstanceId());
        System.out.println("任务Id==>" + task.getId());
        System.out.println("任务负责人==>" + task.getAssignee());
        System.out.println("任务名称==>" + task.getName());

        // 4. 根据任务的Id完成任务
        taskService.complete(task.getId());

    }




    //  =========================================== 监听器 =======================================


    // 部署 test listener 的流程实例
    @Test
    public void testDeployment_listener(){
        // 1.获取引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();


        // 2.得到 RepositoryService 实例
        RepositoryService repositoryService = processEngine.getRepositoryService();

        // 3. 使用 repositoryService进行流程部署
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("bpmn/demo_listener.bpmn")  // 添加 bpmn资源
                .addClasspathResource("bpmn/demo_listener.png")   // 添加 png资源
                .name("监听器流程测试")
                .deploy();

        // 4. 输出部署信息
        System.out.println("流程部署ID==>" + deployment.getId());
        System.out.println("流程部署名称==>" + deployment.getName());
    }


    /*
     *  启动  testListener 实例
     * */
    @Test
    public void testTaskListener() {
        // 1.创建 ProcessEngine
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 2.获取RunTimeService
        RuntimeService runtimeService = processEngine.getRuntimeService();
        // 3.启动流程实例
        runtimeService.startProcessInstanceByKey("demo_listener");

    }

    /*
     *   完成个人任务
     * */
    @Test
    public void testCompleteTask_listener() {
        // 1.获取流程引擎
        ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();
        // 获取 TaskService
        TaskService taskService = processEngine.getTaskService();

        Task task = taskService.createTaskQuery()
                .processDefinitionKey("testListener")
                .singleResult();

        System.out.println("流程实例Id==>" + task.getProcessInstanceId());
        System.out.println("任务Id==>" + task.getId());
        System.out.println("任务负责人==>" + task.getAssignee());
        System.out.println("任务名称==>" + task.getName());

        // 4. 根据任务的Id完成任务
        taskService.complete(task.getId());

    }
}
